#pragma once

#include <variant>
#include "git-commit.h"
#include "git-local-branch.h"

namespace git
{

class Head
{
public:
    Head() {}

    Head(const Head &) = delete;

    Head(Head &&b);

    Head &operator=(const Head &b) = delete;

    Head &operator=(Head &&b);

    operator bool() const {
        return std::get_if<std::monostate>(&ref_) == nullptr;
    }

    bool operator==(const Head &b) const;

    const LocalBranch *branch() const {
        return std::get_if<LocalBranch>(&ref_);
    }

    const Commit *commit() const {
        return std::get_if<Commit>(&ref_);
    }

    std::string oid() const;

    bool isDetached() const {
        if (std::get_if<LocalBranch>(&ref_)) {
            return false;
        } else {
            return true;
        }
    }

    bool isAttached() const {
        return !isDetached();
    }

private:

    Head(Commit &&commit)
        : ref_(std::move(commit)) {
    }

    Head(LocalBranch &&branch)
        : ref_(std::move(branch)) {
    }

private:
    std::variant<std::monostate, Commit, LocalBranch> ref_;

    friend class Repo;
};

} // namespace git
